package com.birdy.room.action;

import com.birdy.con.AppConst;
import com.birdy.dto.Response;
import com.birdy.exception.ServiceException;
import com.birdy.jwt.service.ITokenService;
import com.birdy.jwt.vo.Pair;
import com.birdy.redis.RedisFactory;
import com.birdy.redis.code.RedisSettingCode;
import com.birdy.room.service.IRoomService;
import com.birdy.user.service.IUserService;
import com.birdy.vo.Card;
import com.birdy.vo.Room;
import com.birdy.vo.RoomSetting;
import com.birdy.ws.code.MessageCode;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author birdy
 * @date 2022/4/11 6:05 PM
 */
@Slf4j
@RestController
@RequestMapping("/room/")
public class RoomAction {

    @Autowired
    public ITokenService tokenService;
    @Autowired
    public IUserService userService;
    @Autowired
    public IRoomService roomService;
    @PostMapping("create")
    public Response createRoom(@RequestBody RoomSetting roomSetting) {
        List<Card> cardList = roomSetting.getCardList();
        int sum = 0;
        for (Card card : cardList) {
            sum += card.getCardSelected();
        }
        Room room = null;
        try {
            String openid = tokenService.getOpenid(roomSetting.getOwnerToken());
            room = new Room(openid);
            roomService.addRoom(room);
            RedisReactiveCommands<String, String> commands = RedisFactory.getRedisCommand();
            final int ROOM_ID = room.getId();
            commands.hset(RedisSettingCode.ROOM_PREFIX.getKey() + ROOM_ID,
                    RedisSettingCode.STATUS_NOT_START.getKey(),
                    RedisSettingCode.STATUS_NOT_START.getValue()).subscribe();
            commands.hset(RedisSettingCode.ROOM_PREFIX.getKey() + ROOM_ID,
                    RedisSettingCode.USER_NUM.getKey(),
                    String.valueOf(sum)).subscribe();
            Flux.fromIterable(cardList).flatMap(card -> {
                if (card.getCardSelected() > 0) {
                    return commands.hset(RedisSettingCode.ROOM_PREFIX.getKey() + ROOM_ID,
                            RedisSettingCode.CARD_PREFIX.getKey() + card.getCardRole(),
                            String.valueOf(card.getCardSelected()));
                }
                return Flux.empty();
            }).subscribe();
            commands.expire(RedisSettingCode.ROOM_PREFIX.getKey() + ROOM_ID, AppConst.ROOM_EXPIRE_TIME).subscribe();
        } catch (ServiceException e) {
            log.error("create room error", e);
            return Response.builder().res(MessageCode.ROOM_CREATE_FAILED.getCode())
                    .msg(MessageCode.ROOM_CREATE_FAILED.getMessage()).build();
        } catch (Exception e) {
            log.error("createRoom error", e);
            if (room != null) {
                roomService.deleteRoom(room.getId());
            }
            return Response.builder().res(MessageCode.ROOM_CREATE_FAILED.getCode())
                    .msg(MessageCode.ROOM_CREATE_FAILED.getMessage()).build();
        }
        return Response.builder().res(MessageCode.ROOM_CREATE.getCode())
                .msg(MessageCode.ROOM_CREATE.getMessage())
                .data(AppConst.KEY_ROOM_ID, room.getId()).build();
    }

    @GetMapping("settings")
    public Response getSettings(@RequestParam("room_id") int roomId) throws InterruptedException {
        Room room = roomService.getRoomInfo(roomId);
        if (room == null) {
            return Response.builder().res(Response.FAILED).msg("房间号异常").build();
        }
        RedisReactiveCommands<String, String> commands = RedisFactory.getRedisCommand();
        Response.ResponseBuilder builder = Response.builder();
        ArrayList<Card> cards = new ArrayList<>();
        final CountDownLatch countDownLatch = new CountDownLatch(1); // 发送等待
        commands.hgetall(RedisSettingCode.ROOM_PREFIX.getKey() + roomId)
                .doOnComplete(new Thread(countDownLatch::countDown))
                .subscribe(
                map -> {
                    String key = map.getKey();
                    if (key != null && key.startsWith(RedisSettingCode.CARD_PREFIX.getKey())) {
                        cards.add(new Card(key.substring(RedisSettingCode.CARD_PREFIX.getKey().length()), Integer.parseInt(map.getValue())));
                    } else {
                        builder.data(map.getKey(), map.getValue());
                    }
                    System.out.println(map.getKey() + ": " + map.getValue());
                }
        );
        // 等待执行完成
        boolean await = countDownLatch.await(1, TimeUnit.SECONDS);
        if (!await) {
            log.error("countDownLatch await timeout!");
            return Response.builder().res(Response.FAILED).msg("获取房间信息超时").build();
        }
        return builder.res(Response.SUCCESS).msg("success")
                .data(AppConst.KEY_CARD_LIST, cards).build();
    }
}
